package ai.ann;

import java.awt.Frame;
import java.awt.Label;
import java.io.IOException;

import util.essential.VariableValueGetter;

/**
 * @author S.A.M.G.
 * This class is an interface for every neural network structure that
 * would be implemented in this frame work.
 */
public interface NeuralNetwork {
//	Constants:
	/*
	 * This is the layers folder name: Here is where weight matrixes are
	 * storing them. 
	 * */
	//static final String CONFIGURATION_FILE_NAME = "D:/Sw/properties";
	//static final String CONFIGURATION_FILE_NAME = "./properties";
	/**
	 * This is the value getter that allows to get the configuration variable values.
	 */
	static final VariableValueGetter valueGetter = new VariableValueGetter(Property.CONFIGURATION_FILE_NAME);
	/**
	 * This constant allows to set the fourth channel of ilumination tone.
	 */
	static final boolean WITH_ILUMINATION_CHANNEL = (NeuralNetwork.valueGetter.getStringValue("with_ilumination_channel")).equals("true");
	/**
	 * This constant sets the number of channels of an image pixel.
	 * This is set in the properties file.
	 */
	static final short INPUT_CHANNELS = Short.parseShort(NeuralNetwork.valueGetter.getStringValue("input_channels"));
	/**
	 * This constant sets the number of inputs artificial neurons of the neural network.
	 * This is set in the properties file.
	 */
	static final short INPUT_NEURON_NUMBER =(short) (Math.pow(Short.parseShort(NeuralNetwork.valueGetter.getStringValue("taste_size")), 2)*
															((NeuralNetwork.WITH_ILUMINATION_CHANNEL)?(NeuralNetwork.INPUT_CHANNELS+1):NeuralNetwork.INPUT_CHANNELS));
	/**
	 * This constant sets the number of hidden artificial neurons of the neural network.
	 * This is set in the properties file.
	 */
	static final short HIDDEN_NEURON_NUMBER = Short.parseShort(NeuralNetwork.valueGetter.getStringValue("hidden_layer_neurons_number"));
	/**
	 * This constant sets the number of output artificial neurons of the neural network.
	 * This is set in the properties file.
	 */
	static final int NUMBER_OF_OUTPUTS = Integer.parseInt(NeuralNetwork.valueGetter.getStringValue("number_of_outputs"));
	/**
	 * This constant is to address the neural network trainning mode. 
	 */
	static final boolean TRAINING_MODE = true;
	/**
	 * This constant is to address the neural network execution mode.
	 */
	static final boolean EXECUTION_MODE = false;
	/**
	 * ¿?...I don't remember.  -_-u
	 */
	final String LAYER_FOLDER = "layers";
	
	//Types of Neural Network:
	/**
	 * This constant is to address the single (1 hidden layer) neural network structure.
	 */
	static final short SINGLE = 1;
	/**
	 * This constant is to address the complex (2 hidden layer) neural network structure.
	 */
	static final short COMPLEX = 2;
	
	//Methods:
	/**
	 * This method allows to get the neural network.
	 * @param input as an array. This is the input values for each input neurons of the neural network.
	 * @return neural neural network outputs recognition values.
	 */
	public abstract double[] stimulate(double[] input);
	/**
	 * this method allows to train the neural network.
	 * @param amountPatternTrainn
	 * @param ciclesToTrainn
	 */
	public void startTrainnigNeuralNetwork( int amountPatternTrainn, int ciclesToTrainn);
	/**
	 * This method allows to save the current neural network structure.
	 * @param fileName is the neural network output file name.
	 * @throws IOException
	 */
	public void save(String fileName)throws IOException;
	//Training MiniGUI:
	/**
	 * @author S.A.M.G.
	 * This nested class is to show the trainning progress.
	 */
	public class MiniGUI extends Frame{
		/**
		 * 
		 */
		private static final long serialVersionUID = 1L;
		private Label info;
		public MiniGUI(){
			//super(new Frame("Neural Network MiniTrainer Feed-Back"));
			super("Neural Network MiniTrainer Feed-Back");
			this.info = new Label("...");
			this.add(this.info);
			this.setSize(500,100);
			//this.setEnabled(false);
			this.setAlwaysOnTop(true);
			this.setVisible(true);
		}
		/**
		 * This method shows the "msg" messege.
		 * @param msg
		 */
		public void msg(String msg){
			this.info.setText(msg);
		}
		/**
		 * This method is just for close the mini frame.
		 */
		public void close(){
			this.setVisible(false);
			this.dispose();
		}
	}
}
